package ro.ubbcluj.cs.validation.framework.servlets;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import ro.ubbcluj.cs.validation.framework.core.ParameterName;
import ro.ubbcluj.cs.validation.framework.core.ValidationRule;
import ro.ubbcluj.cs.validation.framework.core.ValidationRuleType;
import ro.ubbcluj.cs.validation.framework.model.Validator;

public class ValidationServlet extends HttpServlet {

	private static final long serialVersionUID = 947750499622077398L;
	
	 /**
     * @see HttpServlet#HttpServlet()
     */
    public ValidationServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	@SuppressWarnings("unchecked")
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String actionURI = request.getHeader("referer");
		actionURI = actionURI.substring(actionURI.indexOf(request.getContextPath())+request.getContextPath().length(), actionURI.length());
		if (StringUtils.isNotEmpty(request.getParameter("sourcePageURI"))) {
			actionURI = request.getParameter("sourcePageURI");
		}
		if (StringUtils.isNotEmpty(request.getParameter("origActionURI"))) {
			List<Validator> validators = processRequestParameters(request.getParameterMap());
			boolean sendBack = false;
			for(Validator v : validators) {
				Map<String, String> messages = v.validate();
				if (!messages.isEmpty()) {
					sendBack = true;
				}
				for(String m : messages.keySet()) {
					request.setAttribute(m, messages.get(m));
				}
			}
			if (!sendBack) {
				actionURI = request.getParameter("origActionURI");
			}
		}
		RequestDispatcher dispatcher = request.getRequestDispatcher(actionURI);
	    dispatcher.forward(request, response);
	}

	private List<Validator> processRequestParameters(Map<String, String[]> parameterMap) {
		List<Validator> validators = new ArrayList<Validator>();
		for(String pName : parameterMap.keySet()){
			Matcher m = Pattern.compile("([\\w]+:)?validator:([\\w]+):vidx([1-9]+)").matcher(pName);
			if (m.matches() && findInputField(parameterMap.keySet(), m.group(2)) != null){
				List<ValidationRule> rules = new ArrayList<ValidationRule>();
				for(String pValue : parameterMap.get(pName)){
					ValidationRule rule = new ValidationRule();
					rule.setType(ValidationRuleType.valueOf(pValue.substring(0, pValue.indexOf(":"))));
					Map<ParameterName, String> validationParameter = new HashMap<ParameterName, String>();
					if (!pValue.endsWith(":")) {
						for(String pnv : pValue.substring(pValue.indexOf(":")+1).split(";")){
							validationParameter.put(ParameterName.valueOf(pnv.substring(0, pnv.indexOf("="))), pnv.substring(pnv.indexOf("=")+1));
						}
					}
					rule.setParameters(validationParameter);
					rules.add(rule);
				}
				String validatorId = m.group(3);
				String inputFieldName = findInputField(parameterMap.keySet(), m.group(2));
				validators.add(new Validator(validatorId, inputFieldName, parameterMap.get(inputFieldName), rules));
			}
		}
		return validators;
	}
	
	private String findInputField(Set<String> fieldNames, String searchedField){
		for(String name : fieldNames){
			if (name.endsWith(":"+searchedField)){
				return name;
			}
		}
		return null;
	}
}
